package com.netease.nimlib.fts.model;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import java.util.ArrayList;
import java.util.List;

public final class NIMIndexStat {
    private final String path;

    private SQLiteDatabase db;

    public NIMIndexStat(String path) {
        this.path = path;
    }

    public final void open() {
        db = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READWRITE);

        ensureTokenTable();
    }

    public final void close() {
        if (db != null) {
            db.close();
        }
    }

    private void ensureTokenTable() {
        if (db == null) {
            return;
        }

        db.execSQL("CREATE VIRTUAL TABLE IF NOT EXISTS FtsIndexMessage_token USING fts4aux(FtsIndexMessage)");
    }

    public final String getTokenCount() {
        List<String[]> rows = query("select count(*) from FtsIndexMessage_token where col='*'");
        return rows != null ? rows.get(0)[0] : null;
    }

    /**
     * @param count documents or occurrences count, -1 as start point
     * @param limit record limit
     * @param doc documents or occurrences
     * @param asc ascend or descend
     */
    public final List<String[]> getTokens(int count, int limit, boolean doc, boolean asc) {
        StringBuilder sb = new StringBuilder();

        // basic
        sb.append("select term,documents,occurrences from FtsIndexMessage_token where col='*'");

        // anchor
        if (count != -1) {
            sb.append(" and ");
            sb.append(doc ? "documents" : "occurrences");
            sb.append(" ");
            sb.append(asc ? ">" : "<");
            sb.append(" ");
            sb.append(count);
        }

        // order by
        sb.append(" order by ");
        sb.append(doc ? "documents" : "occurrences");
        sb.append(" ");
        sb.append(asc ? "asc" : "desc");

        // limit
        sb.append(" limit ");
        sb.append(limit);

        return query(sb.toString());
    }

    public final String getIndexCount() {
        List<String[]> rows = query("select count(*) from FtsIndexMessage_content");
        return rows != null ? rows.get(0)[0] : null;
    }

    public final String getMetaCount() {
        List<String[]> rows = query("select count(*) from FtsMetaMessage where status=0");
        return rows != null ? rows.get(0)[0] : null;
    }

    public final String getMetaCount2() {
        List<String[]> rows = query("select count(*) from FtsMetaMessage");
        return rows != null ? rows.get(0)[0] : null;
    }

    public final String getMetaDistinctIdCount() {
        List<String[]> rows = query("select count(distinct id) from FtsMetaMessage where status=0");
        return rows != null ? rows.get(0)[0] : null;
    }

    public final String getMetaDistinctIdCount2() {
        List<String[]> rows = query("select count(distinct id) from FtsMetaMessage");
        return rows != null ? rows.get(0)[0] : null;
    }

    public final List<String[]> getMetaIdCount() {
        return query("select id,count(*),status from FtsMetaMessage where status=0 group by id");
    }

    public final List<String[]> getMetaIdCount2() {
        return query("select id,count(*),status from FtsMetaMessage where group by id");
    }

    private List<String[]> query(String sql) {
        if (db == null) {
            return null;
        }

        List<String[]> rows = new ArrayList<String[]>();

        Cursor cursor = null;

        try {
            cursor = db.rawQuery(sql, null);
            if (cursor != null) {
                int columns = cursor.getColumnCount();

                while (cursor.moveToNext()) {
                    String[] row = new String[columns];
                    for (int column = 0; column < columns; column++) {
                        row[column] = cursor.getString(column);
                    }
                    rows.add(row);
                }
            }
        } catch (Throwable tr) {
            tr.printStackTrace();
        } finally {
            if (cursor != null) {
                try {
                    cursor.close();
                } catch (Throwable tr) {
                    tr.printStackTrace();
                }
            }
        }

        return rows;
    }
}